#include <stdio.h>

#include "EventLib.h"

#include <GLUT/glut.h>

char keys[255];
qEventRegistry *evt_reg;
qEntity *ent;
qEntity *ent2;
int mx;
int my;

void mouse_delta(qEvent *evt, qEntity *ent)
{
	extern EventState *gp_EventState;
	printf("<%d , %d>\n", evt->get_mouse_x() - gp_EventState->mouse.x,
							evt->get_mouse_y() - gp_EventState->mouse.y);
}

void native_event(qEvent *evt, qEntity *ent)
{
	if(evt->getType() == KEY_EVENT)
	{
		switch (evt->get_key_code()) {
			case 'j' : { ent->setX(ent->getX()-0.15f); break; }
			case 'l' : { ent->setX(ent->getX()+0.15f); break; }
			case 'i' : { ent->setY(ent->getY()+0.15f); break; }
			case 'k' : { ent->setY(ent->getY()-0.15f); break; }
		}
	}
}


void push_key_events(qEventRegistry *reg, char keys[256])
{
    for(int a = 0; a < 256; a++)
    {
        if(keys[a]==1)
            reg->push_event(qEvent(a, DOWN, KEY_EVENT));
    }
}

void display(void)
{
    push_key_events(evt_reg, keys);
    evt_reg->process_events();
	
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	
    glPushMatrix();
    glTranslatef(ent->getX(), ent->getY(), 0);
    glBegin(GL_QUADS);
    glVertex2f(-10, -10);
    glVertex2f(10, -10);
    glVertex2f(10, 10);
    glVertex2f(-10, 10);
    glEnd();
    glPopMatrix();
	
	glPushMatrix();
    glTranslatef(ent2->getX(), ent2->getY(), 0);
    glBegin(GL_QUADS);
    glVertex2f(-10, -10);
    glVertex2f(10, -10);
    glVertex2f(10, 10);
    glVertex2f(-10, 10);
    glEnd();
    glPopMatrix();
	
    glutSwapBuffers();
}

void reshape(int width, int height)
{
    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0, width, 0, height);
    glMatrixMode(GL_MODELVIEW);
}

void idle(void)
{
    glutPostRedisplay();
}


void KeyDown(unsigned char key, int x, int y)
{
    keys[key] = 1;
}

void KeyUp(unsigned char key, int x, int y)
{
    keys[key] = 0;
	evt_reg->push_event(qEvent(key, UP, KEY_EVENT));
}

void PassiveMouse(int _x, int _y)
{
    evt_reg->push_event(qEvent(_x, 480-_y, MOUSE_EVENT));
    mx = _x;
    my = _y;
}

int main(int argc, char **argv)
{
    ent = new qEntity();
    ent->setX(10);
    ent->setY(10);
	
	ent2 = new qEntity();
    ent2->setX(100);
    ent2->setY(100);
	
    // script engine
	qScriptEngine *engine = new qScriptEngine();
	
	// register scriptables on script side.
    engine->RegisterScriptable<qComponent>();
    engine->RegisterScriptable<qEntity>();
    engine->RegisterScriptable<qEvent>();
	
	// make a module called ent_move.
	qScriptModule *mod = engine->pGetScriptModule("ent_move");
	
	// load 2 files to it.
	mod->addSectionFromFile("io_def.as");
    mod->addSectionFromFile("test.as");
	
	// build files
    mod->buildScript();
	
	//get ON_EVENT from ent_move module
    qScriptExec *exe = engine->pGetScriptExec("ent_move", "void ON_EVENT(qEvent &evt, qEntity &t)");
	
	evt_reg = new qEventRegistry();
	
	// pair listeners to handlers.
	REGISTER_PAIR(evt_reg, qEventListener, qScriptEventHandler<qEntity>, ent, exe);
	
	REGISTER_PAIR(evt_reg, qKeyEventListener, qNativeEventHandler<qEntity>, ent2, native_event);
	
	REGISTER_PAIR(evt_reg, qMouseEventListener, qNativeEventHandler<qEntity>, ent2, mouse_delta);
	
	
	
    glutInit(&argc, argv);
	
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
    glutInitWindowSize(640, 480);
	
    glutCreateWindow("qeventlib example");
	
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutIdleFunc(idle);
	
    glutKeyboardFunc(KeyDown);
    glutKeyboardUpFunc(KeyUp);
    glutPassiveMotionFunc(PassiveMouse);
	
    glutMainLoop();
	
	
    return 0;
}
